class Compile {
    constructor(el, vm) {
        this.$vm = vm
        this.$el = document.querySelector(el)
        // 获取所有的子元素
        this.$fragment = this.nodeToFragment(this.$el)
        this.compileElement(this.$fragment)
        this.$el.appendChild(this.$fragment)
        // Array.from() 是转换成数组
    }
    nodeToFragment(el) {
        let fragment = document.createDocumentFragment()
        let child
        while (child = el.firstChild) {
            fragment.appendChild(child)
        }
        return fragment
    }
    compileElement(el) {
        let childNodes = el.childNodes
        Array.from(childNodes).forEach(node => {
            let text = node.textContent
            // 正则匹配
            let reg = /\{\{(.*)\}\}/
            if (this.isElementNode(node)) {
                // 如果是标签
                this.compile(node)
            } else if (this.isTextNode(node) && reg.test(text)) {
                // 文本节点 并且包含{{}}  文本为 RegExp.$1
                this.compileText(node, RegExp.$1)
            }
            if (node.childNodes && node.childNodes.length) {
                this.compileElement(node)
            }
        })
    }
    isElementNode(node) { //nodeType1 是标签
        return node.nodeType == 1
    }
    isTextNode(node) { //nodeType3 是文本
        return node.nodeType == 3
    }
    compile(node) {
        let attrs = node.attributes
        Array.from(attrs).forEach(v => {
            const attrName = v.name
            const exp = v.value 
            if (this.isVueDirective(attrName)) {
                // 是vue的属性
                // 过滤到z-
                const dir = attrName.slice(2)
                if (this[dir]) {
                    this[dir](node, this.$vm, exp)
                }
            }
            if (this.isVueEvent(attrName)) {
                // 是绑定的事件
                // @click ==> click
                let action = attrName.substring(1)
                this.eventHander(node,this.$vm,exp,action)
            }
        })
    }
    compileText(node, exp) {
        this.text(node, this.$vm, exp)
    }
    isVueDirective(name) {
        return name.indexOf('z-') == 0
    }
    isVueEvent(name) {
        return name.indexOf('@') == 0
    }
    text(node, vm, exp) {
        this.update(node, vm, exp, 'text')
    }
    model(node, vm, exp) {
        this.update(node, vm, exp, 'model')
        // 双向绑定  做数据修改
        node.addEventListener('input', e => {
            const newValue = e.target.value
            vm[exp] = newValue
        })
    }
    html(node, vm, exp) {
        this.update(node, vm, exp, 'html')
    }
    update(node, vm, exp, dir) {
        // 实际更新操作
        const fn = this[dir + "Updater"]
        fn && fn(node, vm[exp])
        // 自动添加依赖
        new watch(vm,exp,value=>{
            fn && fn(node,value)
        })

    }
    textUpdater(node, value) {
        node.textContent = value
    }
    htmlUpdater(node, value) {
        node.innerHTML = value
    }
    modelUpdater(node,value){
        node.value = value
    }
    eventHander(node,vm,exp,action){
        const fn = vm.$options.methods &&  vm.$options.methods[exp]
        node.addEventListener(action,fn.bind(vm),false)
    }
}